%     FASTENER DOCTOR - программа для лечения и конвертации крепежа
%     Copyright (C) 2018  Михаил Козлов
%     Сайт проекта: <http://www.fastenerdoctor.ru/>
%     Адрес электронной почты для связи с разработчиком:
%     <doctor.fastener@gmail.com>
% 
%     Эта программа является свободным программным обеспечением: Вы можете
%     распространять ее и/или изменять, соблюдая условия Универсальной общественной
%     лицензии GNU, опубликованной Фондом свободного программного обеспечения,
%     либо редакции 3, либо (на Ваше усмотрение) любой редакции, выпущенной позже.
% 
%     Эта программа распространяется в надежде на то, что она окажется полезной,
%     но БЕЗ КАКИХ-ЛИБО ГАРАНТИЙ, включая даже подразумеваемую гарантию ТОВАРНОЙ ПРИГОДНОСТИ,
%     либо ПРИГОДНОСТИ ДЛЯ ОПРЕДЕЛЕННЫХ ЦЕЛЕЙ. Ознакомьтесь с Универсальной общественной
%     лицензией GNU для получения более подробной информации.
% 
%     Вы должны были получить копию Универсальной общественной лицензии GNU
%     вместе с этой программой. Если Вы ее не получили, то перейдите по адресу:
%     <http://www.gnu.org/licenses/>.
% 
%     This program is free software: you can redistribute it and/or modify
%     it under the terms of the GNU General Public License as published by
%     the Free Software Foundation, either version 3 of the License, or
%     (at your option) any later version.
% 
%     This program is distributed in the hope that it will be useful,
%     but WITHOUT ANY WARRANTY; without even the implied warranty of
%     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
%     GNU General Public License for more details.
% 
%     You should have received a copy of the GNU General Public License
%     along with this program.  If not, see <https://www.gnu.org/licenses/>.

function [An_Coord_Repair_Ctr, Ref_Coord_Repair_Ctr, Modified_Axial_Constraint_Counter, Repaired_RBAR_DOFs_Counter] = Repair_RutFast_RBAR_DOFs(Fastener_Index, RutFast_Axial_Constraint)

global ErrCode;

global DB_NODES;
global DB_MPC;
global DB_COORD;

global AT_NODES;
global AT_MPC;
global AT_COORD;

global DB_FASTENERS;

global Coord_Z_Bolt_Axis_deg_tolerance;

% Инициализация счетчиков
An_Coord_Repair_Ctr = 0;
Ref_Coord_Repair_Ctr = 0;
Modified_Axial_Constraint_Counter = 0;
Repaired_RBAR_DOFs_Counter = 0;

% Исправление систем координат анализа в болте
[temp_counter_1, temp_counter_2] = Repair_RutFast_Coord(Fastener_Index);

if (ErrCode < 0)
    return;
end

% Обновление счетчиков
An_Coord_Repair_Ctr = An_Coord_Repair_Ctr + temp_counter_1;
Ref_Coord_Repair_Ctr = Ref_Coord_Repair_Ctr + temp_counter_2;

% Получение общей системы координат болта
General_Coord_ID = DB_NODES{AT_NODES(DB_FASTENERS{Fastener_Index}.Shank_nodes(1))}.Analysis_CID;

% Ось Z общей системы координат болта
if (General_Coord_ID == 0)
    Coord_e_z = [0;0;1];
else
    Coord_e_z = DB_COORD{AT_COORD(General_Coord_ID)}.e_z;
end

% Получение оси болта
[Axis_Point_1, Axis_Point_2, Axis_vector] = Get_Fastener_Axis(Fastener_Index); %#ok<ASGLU>

if (ErrCode < 0)
    return;
end

% Тест на сонаправленность оси Z с осью болта
Angle = acosd(dot(Coord_e_z, Axis_vector)); % Вектора имеют единичную длину

if (Angle > 90)
    Angle = 180 - Angle;
end

if (Angle > Coord_Z_Bolt_Axis_deg_tolerance)
    
    fprintf (1, '\nОшибка функции Repair_RutFast_RBAR_DOFs: ось Z общей системы координат болта %i не сонаправлена с осью болта !\n', Fastener_Index);
    fprintf (1, 'Обратетись к разработчику для решения этого вопроса.\n');
    ErrCode = -1;
    return;
    
end

% Старые степени свободы RBAR в головке болта
Head_MPC_ID = DB_FASTENERS{Fastener_Index}.RBAR_MPCs(DB_FASTENERS{Fastener_Index}.Head_MPC_Index);
Old_Head_DOF = DB_MPC{AT_MPC(Head_MPC_ID)}.dep_DOF;

% Три вида степеней свободы
switch RutFast_Axial_Constraint
    case 'RBAR_DOF'
        DOF_Type_1 = 3456;
    case 'USER_BC'
        DOF_Type_1 = 345;
    otherwise
        fprintf (1, '\nОшибка функции Repair_RutFast_RBAR_DOFs: недопустимое значение параметра RutFast_Axial_Constraint [%s] !\n', RutFast_Axial_Constraint);
        ErrCode = -1;
        return;
end

DOF_Type_2 = 345;
DOF_Type_3 = 45;

% Три вида индексов
All_Indeces = zeros(DB_FASTENERS{Fastener_Index}.N_layers + 1,1);

for i=1:size(All_Indeces, 1)
    All_Indeces(i) = i;
end

if (DB_FASTENERS{Fastener_Index}.Head_MPC_Index ~= 1)
    flip(All_Indeces, 1);
end

Index_Type_1 = All_Indeces(1);
Indeces_Type_2 = All_Indeces(2:DB_FASTENERS{Fastener_Index}.N_layers);
Index_Type_3 = All_Indeces(DB_FASTENERS{Fastener_Index}.N_layers + 1);

% Исправление 1 типа
if (~Compare_DOFs(DB_MPC{AT_MPC(DB_FASTENERS{Fastener_Index}.RBAR_MPCs(Index_Type_1))}.dep_DOF, DOF_Type_1))
    
    MPC_ID = DB_FASTENERS{Fastener_Index}.RBAR_MPCs(Index_Type_1);
    Ind_Node = DB_MPC{AT_MPC(DB_FASTENERS{Fastener_Index}.RBAR_MPCs(Index_Type_1))}.ind_grid;
    Dep_Node = DB_MPC{AT_MPC(DB_FASTENERS{Fastener_Index}.RBAR_MPCs(Index_Type_1))}.dep_grid;
    Dep_DOFs = DOF_Type_1;
    
    Append_To_Output(PCL_MPC_Modify_RBAR(MPC_ID, Ind_Node, Dep_Node, Dep_DOFs));
    DB_MPC_Modify_RBAR(MPC_ID, Ind_Node, Dep_Node, Dep_DOFs);
    
    if (ErrCode < 0)
        return;
    end
    
    String_DOF_Type_1 = num2str(DOF_Type_1);
    String_Old_Head_DOF = num2str(Old_Head_DOF);
        
    Flags_DOF_Type_1 = zeros(6,1);
    Flags_Old_Head_DOF = zeros(6,1);
    
    for i=1:numel(String_DOF_Type_1)
        Flags_DOF_Type_1(str2double(String_DOF_Type_1(i))) = 1;
    end

    for i=1:numel(String_Old_Head_DOF)
        Flags_Old_Head_DOF(str2double(String_Old_Head_DOF(i))) = 1;
    end
    
    if (Flags_DOF_Type_1(6) ~= Flags_Old_Head_DOF(6))
        Modified_Axial_Constraint_Counter = Modified_Axial_Constraint_Counter + 1;
    end
    
    if (~isequal(Flags_DOF_Type_1(1:5), Flags_Old_Head_DOF(1:5)))
        Repaired_RBAR_DOFs_Counter = Repaired_RBAR_DOFs_Counter + 1;
    end
    
end

% Исправление 2 типа
for i=1:size(Indeces_Type_2,1)
    
    if (~Compare_DOFs(DB_MPC{AT_MPC(DB_FASTENERS{Fastener_Index}.RBAR_MPCs(Indeces_Type_2(i)))}.dep_DOF, DOF_Type_2))
        
        MPC_ID = DB_FASTENERS{Fastener_Index}.RBAR_MPCs(Indeces_Type_2(i));
        Ind_Node = DB_MPC{AT_MPC(DB_FASTENERS{Fastener_Index}.RBAR_MPCs(Indeces_Type_2(i)))}.ind_grid;
        Dep_Node = DB_MPC{AT_MPC(DB_FASTENERS{Fastener_Index}.RBAR_MPCs(Indeces_Type_2(i)))}.dep_grid;
        Dep_DOFs = DOF_Type_2;

        Append_To_Output(PCL_MPC_Modify_RBAR(MPC_ID, Ind_Node, Dep_Node, Dep_DOFs));
        DB_MPC_Modify_RBAR(MPC_ID, Ind_Node, Dep_Node, Dep_DOFs);

        if (ErrCode < 0)
            return;
        end
        
        Repaired_RBAR_DOFs_Counter = Repaired_RBAR_DOFs_Counter + 1;

    end
    
end

% Исправление 3 типа
if (~Compare_DOFs(DB_MPC{AT_MPC(DB_FASTENERS{Fastener_Index}.RBAR_MPCs(Index_Type_3))}.dep_DOF, DOF_Type_3))
    
    MPC_ID = DB_FASTENERS{Fastener_Index}.RBAR_MPCs(Index_Type_3);
    Ind_Node = DB_MPC{AT_MPC(DB_FASTENERS{Fastener_Index}.RBAR_MPCs(Index_Type_3))}.ind_grid;
    Dep_Node = DB_MPC{AT_MPC(DB_FASTENERS{Fastener_Index}.RBAR_MPCs(Index_Type_3))}.dep_grid;
    Dep_DOFs = DOF_Type_3;
    
    Append_To_Output(PCL_MPC_Modify_RBAR(MPC_ID, Ind_Node, Dep_Node, Dep_DOFs));
    DB_MPC_Modify_RBAR(MPC_ID, Ind_Node, Dep_Node, Dep_DOFs);
    
    if (ErrCode < 0)
        return;
    end
    
    Repaired_RBAR_DOFs_Counter = Repaired_RBAR_DOFs_Counter + 1;
    
end
